/**
 * matrix44_tests.js
 * 
 * Test Matrix44 functionality.
 * 
 * @author floh
 * 
 * (C) 2010 A.Weissflog
 */

Matrix44.TestDefaultConstructor = function()
{
	var m = new Matrix44();
	return (m.r0.x == 1.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
	       (m.r1.x == 0.0) && (m.r1.y == 1.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
		   (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 1.0) && (m.r2.w == 0.0) &&
		   (m.r3.x == 0.0) && (m.r3.y == 0.0) && (m.r3.z == 0.0) && (m.r3.w == 1.0);
}

Matrix44.TestFromRows = function()
{
	var row0 = Float4.FromValues(1.0, 2.0, 3.0, 4.0);
	var row1 = Float4.FromValues(5.0, 6.0, 7.0, 8.0);
	var row2 = Float4.FromValues(9.0, 10.0, 11.0, 12.0);
	var row3 = Float4.FromValues(13.0, 14.0, 15.0, 16.0);
	var m = Matrix44.FromRows(row0, row1, row2, row3);
	return (m.r0.x == 1.0) && (m.r0.y == 2.0) && (m.r0.z == 3.0) && (m.r0.w == 4.0) &&
	       (m.r1.x == 5.0) && (m.r1.y == 6.0) && (m.r1.z == 7.0) && (m.r1.w == 8.0) &&
		   (m.r2.x == 9.0) && (m.r2.y == 10.0) && (m.r2.z == 11.0) && (m.r2.w == 12.0) &&
		   (m.r3.x == 13.0) && (m.r3.y == 14.0) && (m.r3.z == 15.0) && (m.r3.w == 16.0);
}

Matrix44.TestFromValues = function()
{
	var m = Matrix44.FromValues(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
	return (m.r0.x == 1.0) && (m.r0.y == 2.0) && (m.r0.z == 3.0) && (m.r0.w == 4.0) &&
		   (m.r1.x == 5.0) && (m.r1.y == 6.0) && (m.r1.z == 7.0) && (m.r1.w == 8.0) &&
		   (m.r2.x == 9.0) && (m.r2.y == 10.0) && (m.r2.z == 11.0) && (m.r2.w == 12.0) &&
		   (m.r3.x == 13.0) && (m.r3.y == 14.0) && (m.r3.z == 15.0) && (m.r3.w == 16.0);
}				

Matrix44.TestFromMatrix44 = function()
{
    var m0 = Matrix44.FromValues(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
    var m = Matrix44.FromMatrix44(m0);
    return (m.r0.x == 1.0) && (m.r0.y == 2.0) && (m.r0.z == 3.0) && (m.r0.w == 4.0) &&
           (m.r1.x == 5.0) && (m.r1.y == 6.0) && (m.r1.z == 7.0) && (m.r1.w == 8.0) &&
           (m.r2.x == 9.0) && (m.r2.y == 10.0) && (m.r2.z == 11.0) && (m.r2.w == 12.0) &&
           (m.r3.x == 13.0) && (m.r3.y == 14.0) && (m.r3.z == 15.0) && (m.r3.w == 16.0);
}					      

Matrix44.TestSetRows = function()
{
    var row0 = Float4.FromValues(1.0, 2.0, 3.0, 4.0);
    var row1 = Float4.FromValues(5.0, 6.0, 7.0, 8.0);
    var row2 = Float4.FromValues(9.0, 10.0, 11.0, 12.0);
    var row3 = Float4.FromValues(13.0, 14.0, 15.0, 16.0);
    var m = new Matrix44;
	m.SetRows(row0, row1, row2, row3);
    return (m.r0.x == 1.0) && (m.r0.y == 2.0) && (m.r0.z == 3.0) && (m.r0.w == 4.0) &&
           (m.r1.x == 5.0) && (m.r1.y == 6.0) && (m.r1.z == 7.0) && (m.r1.w == 8.0) &&
           (m.r2.x == 9.0) && (m.r2.y == 10.0) && (m.r2.z == 11.0) && (m.r2.w == 12.0) &&
           (m.r3.x == 13.0) && (m.r3.y == 14.0) && (m.r3.z == 15.0) && (m.r3.w == 16.0);	
}

Matrix44.TestTranslate = function()
{
    var m = new Matrix44();
	m.Translate(2.0, 3.0, 4.0);
    return (m.r0.x == 1.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 1.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 1.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 2.0) && (m.r3.y == 3.0) && (m.r3.z == 4.0) && (m.r3.w == 1.0);    
}

Matrix44.TestScale = function()
{
    var m = new Matrix44();
	m.Translate(2.0, 3.0, 4.0);
	m.Scale(2.0)	
    return (m.r0.x == 2.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 2.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 2.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 2.0) && (m.r3.y == 3.0) && (m.r3.z == 4.0) && (m.r3.w == 1.0);    
}

Matrix44.TestTransformIdentity = function()
{
    var m = new Matrix44();
	var f0 = Float4.FromValues(2.0, 3.0, 4.0, 5.0);
	var f1 = Matrix44.Transform(f0, m);
	return (f1.x == 2.0) && (f1.y == 3.0) && (f1.z == 4.0) && (f1.w == 5.0);
}

Matrix44.TestTransformPoint = function()
{
	var m = new Matrix44();
	m.Translate(1.0, 2.0, 3.0);
	var f0 = Float4.FromValues(0.0, 0.0, 0.0, 1.0);
	var f1 = Matrix44.Transform(f0, m);
	return (f1.x == 1.0) && (f1.y = 2.0) && (f1.z == 3.0) && (f1.w == 1.0);
}

Matrix44.TestTransformVector = function()
{
	var m = new Matrix44();
	m.Scale(2.0);
	m.Translate(1.0, 2.0, 3.0);
	var f0 = Float4.FromValues(1.0, 2.0, 3.0, 0.0);
	var f1 = Matrix44.Transform(f0, m);
	return (f1.x == 2.0) && (f1.y == 4.0) && (f1.z == 6.0) && (f1.w == 0.0);
}

Matrix44.TestMultiplyByIdentityInplace = function()
{
    var m0 = new Matrix44();
	var m = new Matrix44();
	m.Scale(2.0);
	m.Translate(1.0, 2.0, 3.0);
	m.Multiply(m0);
    return (m.r0.x == 2.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 2.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 2.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 1.0) && (m.r3.y == 2.0) && (m.r3.z == 3.0) && (m.r3.w == 1.0);    
}

Matrix44.TestMultiplyByIdentity = function()
{
    var m0 = new Matrix44();
	var m1 = new Matrix44();
	m1.Scale(2.0);
	m1.Translate(1.0, 2.0, 3.0);
	var m = Matrix44.Multiply(m0, m1);
    return (m.r0.x == 2.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 2.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 2.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 1.0) && (m.r3.y == 2.0) && (m.r3.z == 3.0) && (m.r3.w == 1.0);    
}

Matrix44.TestIdentity = function()
{
	var m = new Matrix44();
    m.Scale(2.0);
	m.Translate(1.0, 2.0, 3.0);
	m.Identity();
    return (m.r0.x == 1.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 1.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 1.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 0.0) && (m.r3.y == 0.0) && (m.r3.z == 0.0) && (m.r3.w == 1.0);
}

Matrix44.TestDeterminant = function()
{
	var m = Matrix44.RotationX(1.0);
	var det = m.Determinant();
	return det == 1.0;
}

Matrix44.TestInverseIdentity = function()

{
	var m0 = new Matrix44();
	var m = Matrix44.Inverse(m0);
    return (m.r0.x == 1.0) && (m.r0.y == 0.0) && (m.r0.z == 0.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 0.0) && (m.r1.y == 1.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 0.0) && (m.r2.z == 1.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 0.0) && (m.r3.y == 0.0) && (m.r3.z == 0.0) && (m.r3.w == 1.0);
}

Matrix44.TestDoubleInverse = function()
{
	var m0 = Matrix44.RotationX(2.0);
	var m1 = Matrix44.Inverse(m0);
	m1 = Matrix44.Inverse(m1);
	return (m0.r0.x == m1.r0.x) && (m0.r0.y == m1.r0.y) && (m0.r0.z == m1.r0.z) && (m0.r0.w == m1.r0.w) &&
	       (m0.r1.x == m1.r1.x) && (m0.r1.y == m1.r1.y) && (m0.r1.z == m1.r1.z) && (m0.r1.w == m1.r1.w) &&
           (m0.r2.x == m1.r2.x) && (m0.r2.y == m1.r2.y) && (m0.r2.z == m1.r2.z) && (m0.r2.w == m1.r2.w) &&
           (m0.r3.x == m1.r3.x) && (m0.r3.y == m1.r3.y) && (m0.r3.z == m1.r3.z) && (m0.r3.w == m1.r3.w);
}   

Matrix44.TestLookatRh = function()
{
	var eye = Float4.FromValues(3.0, 10.0, -2.0, 1.0);
	var at  = Float4.FromValues(3.0, 2.0, -2.0, 1.0);
	var up  = Float4.FromValues(0.0, 1.0, 0.0, 0.0);
	var m = Matrix44.LookatRh(eye, at, up);
    return (m.r0.x == 0.0) && (m.r0.y == 0.0) && (m.r0.z == 1.0) && (m.r0.w == 0.0) &&
           (m.r1.x == 1.0) && (m.r1.y == 0.0) && (m.r1.z == 0.0) && (m.r1.w == 0.0) &&
           (m.r2.x == 0.0) && (m.r2.y == 1.0) && (m.r2.z == 0.0) && (m.r2.w == 0.0) &&
           (m.r3.x == 3.0) && (m.r3.y == 10.0) && (m.r3.z == -2.0) && (m.r3.w == 1.0);
}

Matrix44.TestOrthoRh = function()
{
	var m0 = Matrix44.OrthoRh(1280.0, 1024.0, 0.1, 100.0);
	var m1 = Matrix44.FromValues(0.001563, 0.0,       0.0, 0.0,
	                                   0.0, 0.001953,       0.0, 0.0,
								       0.0,      0.0,  -0.01001, 0.0,
								       0.0,      0.0, -0.001001, 1.0);
	return Matrix44.Equal(m0, m1, 0.00001);
}

Matrix44.TestPerspFovRh = function()
{
	// note: the Fov is not given in degree but in rad!
	var m0 = Matrix44.PerspFovRh(70, 3.0/4.0, 0.1, 50);
	var m1 = Matrix44.FromValues(2.814039, 0.0,       0.0,  0.0,
	                                   0.0,  2.11053,       0.0,  0.0,
									   0.0,      0.0, -1.002004, -1.0,
									   0.0,      0.0,   -0.1002,  0.0);
    return Matrix44.Equal(m0, m1, 0.00001);	
}

Matrix44.TestPerspRh = function()
{
	var m0 = Matrix44.PerspRh(1280.0, 1024.0, 0.1, 100.0);
	var m1 = Matrix44.FromValues(0.000156, 0.0,      0.0,   0.0,
	                                   0.0, 0.000195,      0.0,   0.0,
									   0.0,      0.0, -1.001001, -1.0,
									   0.0,      0.0,   -0.1001,  0.0);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestRotationAxis = function()
{
	var axis = Float4.Normalize(Float4.FromValues(1.0, 0.2, 2.0, 0.0));
	var m0 = Matrix44.RotationAxis(axis, -2.53652);
	var m1 = Matrix44.FromValues(-0.460861, -0.434427,  0.773873, 0.000000,
	                                    0.579067, -0.807997, -0.108734, 0.000000,
										0.672524,  0.398013,  0.623936, 0.000000,
										0.000000,  0.000000,  0.000000, 1.000000);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestRotationX = function()
{
    var m0 = Matrix44.RotationX(2.0);
	var m1 = Matrix44.FromValues(1.000000,  0.000000,  0.000000, 0.000000,
                                       0.000000, -0.416147,  0.909297, 0.000000,
                                       0.000000, -0.909297, -0.416147, 0.000000,
                                       0.000000,  0.000000,  0.000000, 1.000000);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestRotationY = function()
{
    var m0 = Matrix44.RotationY(-1.7);
    var m1 = Matrix44.FromValues(-0.128845, 0.000000,  0.991665, 0.000000,
                                        0.000000, 1.000000,  0.000000, 0.000000,
                                       -0.991665, 0.000000, -0.128845, 0.000000,
                                        0.000000, 0.000000,  0.000000, 1.000000);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestRotationZ = function()
{
    var m0 = Matrix44.RotationZ(3.1);
    var m1 = Matrix44.FromValues(-0.999135,  0.041581, 0.000000, 0.000000,
                                       -0.041581, -0.999135, 0.000000, 0.000000,
                                        0.000000,  0.000000, 1.000000, 0.000000,
                                        0.000000,  0.000000, 0.000000, 1.000000);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestRotationYawPitchRoll = function()

{
	var m0 = Matrix44.RotationYawPitchRoll(1.0, -0.462, 3.036);
	var m1 = Matrix44.FromValues(-0.576825,  0.094347, 0.811401, 0.0,
                                        0.316042, -0.890177, 0.328181, 0.0,
                                        0.753254,  0.445739, 0.483659, 0.0,
                                             0.0,       0.0,      0.0, 1.0);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestScaling = function()
{
	var m0 = Matrix44.Scaling(2.0, 3.0, 4.0);
	var m1 = Matrix44.FromValues(2.0, 0.0, 0.0, 0.0,
	                                   0.0, 3.0, 0.0, 0.0,
									   0.0, 0.0, 4.0, 0.0,
									   0.0, 0.0, 0.0, 1.0);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestTranslation = function()
{
	var m0 = Matrix44.Translation(2.0, 3.0, 4.0);
	var m1 = Matrix44.FromValues(1.0, 0.0, 0.0, 0.0,
	                                   0.0, 1.0, 0.0, 0.0,
									   0.0, 0.0, 1.0, 0.0,
									   2.0, 3.0, 4.0, 1.0);
    return Matrix44.Equal(m0, m1, 0.00001); 
}

Matrix44.TestTranspose = function()
{
	var m0 = Matrix44.FromValues(1.0, 2.0, 3.0, 4.0,
	                                   5.0, 6.0, 7.0, 8.0,
									   9.0, 10.0, 11.0, 12.0,
									   13.0, 14.0, 15.0, 16.0);
	var m1 = Matrix44.FromValues(1.0, 5.0, 9.0, 13.0,
	                                   2.0, 6.0, 10.0, 14.0,
									   3.0, 7.0, 11.0, 15.0,
									   4.0, 8.0, 12.0, 16.0);
	var m2 = Matrix44.Transpose(m0);
	return Matrix44.Equal(m1, m2, 0.00001);
}

Matrix44.RunTests = function()
{
	testRunner = new TestRunner("Matrix44 Tests");
	testRunner.Add("Default Constructor", Matrix44.TestDefaultConstructor);
	testRunner.Add("Create From Rows", Matrix44.TestFromRows);
    testRunner.Add("Create From Values", Matrix44.TestFromValues);
	testRunner.Add("Create From Matrix44", Matrix44.TestFromMatrix44);
	testRunner.Add("Set Rows", Matrix44.TestSetRows);
	testRunner.Add("Translate", Matrix44.TestTranslate);
	testRunner.Add("Scale", Matrix44.TestScale);
	testRunner.Add("Transform Identity", Matrix44.TestTransformIdentity);
	testRunner.Add("Transform Point", Matrix44.TestTransformPoint);
	testRunner.Add("Transform Vector", Matrix44.TestTransformVector);
	testRunner.Add("Matrix Multiply By Identity Inplace", Matrix44.TestMultiplyByIdentityInplace);
	testRunner.Add("Matrix Multiply By Identity", Matrix44.TestMultiplyByIdentity);  
	testRunner.Add("Set To Identity", Matrix44.TestIdentity); 
	testRunner.Add("Determinant", Matrix44.TestDeterminant);
	testRunner.Add("Identity Inverse", Matrix44.TestInverseIdentity);
	testRunner.Add("Double Inverse", Matrix44.TestDoubleInverse);
	testRunner.Add("Lookat Right Handed", Matrix44.TestLookatRh);
	testRunner.Add("Ortho Right Handed", Matrix44.TestOrthoRh);
	testRunner.Add("Persp Fov Right Handed", Matrix44.TestPerspFovRh);
	testRunner.Add("Persp Right Handed", Matrix44.TestPerspRh);
	testRunner.Add("Rotation General Axis", Matrix44.TestRotationAxis);
	testRunner.Add("Rotation X Axis", Matrix44.TestRotationX);
	testRunner.Add("Rotation Y Axis", Matrix44.TestRotationY);
	testRunner.Add("Rotation Z Axis", Matrix44.TestRotationZ);
	testRunner.Add("Rotation Yaw Pitch Roll", Matrix44.TestRotationYawPitchRoll);
	testRunner.Add("Create Scaling Matrix", Matrix44.TestScaling);
	testRunner.Add("Create Translation Matrix", Matrix44.TestTranslation);
	testRunner.Add("Create Transposed Matrix", Matrix44.TestTranspose);
   	testRunner.Run();
}


